package view.trajectory;

import graphics.engine.ProgramShader;

import java.util.ArrayList;
import java.util.Iterator;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;

import mathematics.Matrix4x4;
import mathematics.geometry.Geometry;

import model.DoorModel;
import model.trajectory.BaseTrajectoryModel;
import model.trajectory.RoomTrajectoryModel;
import model.trajectory.TrajectoryModel;
import model.trajectory.TransitionTrajectoryModel;

import utils.Pair;
import utils.TimeIntervalle;
import view.DoorView;
import view.RoomView;

public class TrajectoryView 
{
	public TrajectoryModel model;
	
	public ArrayList<RoomView> rooms;
	public ArrayList<DoorView> doors;
	
	private boolean hasChanged = false;
	
	public ArrayList<Pair<TimeIntervalle, BaseTrajectoryView>> subTrajectoryViews;
	
	public TrajectoryView(GL gl, TrajectoryModel model, ArrayList<RoomView> rooms, ArrayList<DoorView> doors)
	{
		this.model = model;
		this.rooms = rooms;
		this.doors = doors;
		this.subTrajectoryViews = new ArrayList<Pair<TimeIntervalle, BaseTrajectoryView>>();
		
		BaseTrajectoryView lastSubtrajectory = null;
		
		for(Iterator<Pair<TimeIntervalle, BaseTrajectoryModel>> it = model.subTrajectories.iterator(); it.hasNext();)
		{
			Pair<TimeIntervalle, BaseTrajectoryModel> pair = it.next();
			TimeIntervalle intervalle = pair.key;
			BaseTrajectoryModel subTrajectoryModel = pair.value;
			BaseTrajectoryView subTrajectoryView;
			
			if(subTrajectoryModel.getClass() == RoomTrajectoryModel.class)
			{
				RoomTrajectoryModel roomTrajectoryModel = (RoomTrajectoryModel)subTrajectoryModel;
				subTrajectoryView = new RoomTrajectoryView(gl, roomTrajectoryModel, this.getRoomViewById(roomTrajectoryModel.room.getID()) );
			}
			else
			{
				TransitionTrajectoryModel transitionTrajectoryModel = (TransitionTrajectoryModel)subTrajectoryModel;
				RoomView firstRoomView = this.getRoomViewById(transitionTrajectoryModel.door.FirstRoom.getID());
				RoomView secondRoomView = this.getRoomViewById(transitionTrajectoryModel.door.SecondRoom.getID());
				DoorView doorView = this.getDoorView(transitionTrajectoryModel.door);
				subTrajectoryView = new TransitionTrajectoryView(gl, transitionTrajectoryModel, doorView, firstRoomView, secondRoomView);
				doorView.addSubtrajectoryView((TransitionTrajectoryView)subTrajectoryView);
			}
			if(lastSubtrajectory != null)
			{
				lastSubtrajectory.setNextSubtrajectory(subTrajectoryView);
				subTrajectoryView.setLastSubtrajectory(lastSubtrajectory);
			}
			lastSubtrajectory = subTrajectoryView;
			this.subTrajectoryViews.add(new Pair<TimeIntervalle, BaseTrajectoryView>(intervalle, subTrajectoryView));
		}
	}
		
	private DoorView getDoorView(DoorModel door) 
	{
		for(Iterator<DoorView> it = doors.iterator(); it.hasNext();)
		{
			DoorView doorView = it.next();
			if(doorView.getModel() == door)
			{
				return doorView;
			}
		}
		return null;	
	}

	public void Draw(GLAutoDrawable drawable, ProgramShader programShader, Long logTime, Long beginTime, Long endTime) 
	{
		GL gl = drawable.getGL();
		Matrix4x4 worldMatrix = new Matrix4x4();		
		worldMatrix.setToIdentity();
		gl.glUniformMatrix4fv(programShader.WorldMatrixUniformID, 1, false, worldMatrix.toFloatArray(), 0);		
	}
	
	public RoomView getRoomViewById(int ID)
	{
		for(Iterator<RoomView> it = rooms.iterator(); it.hasNext();)
		{
			RoomView roomView = it.next();
			if(roomView.getModel().getID() == ID)
			{
				return roomView;
			}
		}
		return null;
	}

	public boolean isIntersectedBy(Geometry geometry) {
		for(Iterator<Pair<TimeIntervalle, BaseTrajectoryView>> it = this.subTrajectoryViews.iterator(); it.hasNext();)
		{
			BaseTrajectoryView baseTrajView = it.next().value;
			if(baseTrajView.isIntersectedByDisk(geometry))
			{
				return true;
			}
		}
		return false;
	}

	public void hasChanged(boolean value) {
		// TODO Auto-generated method stub
		this.setHasChanged(value);
		for(Iterator<Pair<TimeIntervalle, BaseTrajectoryView>> it = this.subTrajectoryViews.iterator(); it.hasNext();)
		{
			it.next().value.setHasChanged( true );
		}
	}

	public boolean isHasChanged() {
		return hasChanged;
	}

	public void setHasChanged(boolean hasChanged) {
		this.hasChanged = hasChanged;
	}
}
